package com.purchase.ml.service.sdk.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.purchase.ml.bean.api.Ipay88Back;
import com.purchase.ml.bean.req.order.OrderEditReq;
import com.purchase.ml.bean.sdk.IpayNewDto;
import com.purchase.ml.bean.sdk.IpayQueryDto;
import com.purchase.ml.consts.CommonConsts;
import com.purchase.ml.consts.Constants;
import com.purchase.ml.entity.order.SysPayinfo;
import com.purchase.ml.enums.ConmonStatusEnum;
import com.purchase.ml.enums.OrderStatusEnum;
import com.purchase.ml.enums.RedisCacheEnum;
import com.purchase.ml.mapper.dealer.SysDealerMapper;
import com.purchase.ml.mapper.order.SysPayInfoMapper;
import com.purchase.ml.service.dealer.SysDealerService;
import com.purchase.ml.service.order.SysOrderService;
import com.purchase.ml.service.sdk.Ipay88Service;
import com.purchase.ml.utils.HttpUtil;
import com.purchase.ml.utils.RedisClient;
import com.purchase.ml.utils.SHA256;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import redis.clients.jedis.Jedis;

import java.math.BigDecimal;
import java.security.NoSuchAlgorithmException;
import java.util.*;

@Service
@Slf4j
public class Ipay88ServiceImpl implements Ipay88Service {
//    private String  requestUrl = "https://payment.ipay88.com.my/ePayment/entry.asp";  //请求地址
    private String  queryUrl   = "https://payment.ipay88.com.my/ePayment/enquiry.asp"; // 查询地址
//    private String  responseUrl = "http://shop.xiaoka98.cn/My-Orders/Query";                        //支付完成跳转我方地址
//    private String  backendUrl  = "http://backend.xiaoka98.cn/purchase/ipay88/callback"; //我方接收异步地址
    //    REDIS_IPAY88PAY_ORDER

    @Autowired 
    SysOrderService sysOrderService;

    @Autowired 
    private SysDealerMapper sysDealerMapper;

    @Autowired
    SysDealerService sysDealerService;

    @Autowired
    SysPayInfoMapper payInfoMapper;

    @Override
    public void doQueryToIpay88(IpayQueryDto dto) {
        HashMap<String,String> requestMap = new HashMap<>();
        requestMap.put("MerchantCode",CommonConsts.MERCHANTKEY);
        requestMap.put("RefNo",dto.getRefNo());
        requestMap.put("Amount",dto.getAmount());
        String response = HttpUtil.doPostForm(this.queryUrl,requestMap);
        if(response.equals("00")){
            //更新为已经支付
            if(dto.getPayType() == 0){
                payInfoMapper.updatePayinfoStateByPayId(Long.valueOf(dto.getRefNo()),ConmonStatusEnum.SUCCESS.getCode());
                //更新商户状态 更新支付状态
                OrderEditReq orderEditReq = new OrderEditReq();
                orderEditReq.setOid(Long.valueOf( dto.getRefNo() ));
                orderEditReq.setState(OrderStatusEnum.PAID.getCode().toString());
                sysOrderService.changeOrderState(orderEditReq);

            }else if(dto.getPayType() == 1){
                //更新订单状态 更新支付状态
                payInfoMapper.updatePayinfoStateByPayId(Long.valueOf(dto.getRefNo()), ConmonStatusEnum.SUCCESS.getCode());
                sysDealerMapper.updateDealerStateByDealerId(Long.valueOf(dto.getRefNo()),ConmonStatusEnum.SUCCESS.getCode());
            }
        }
        if(response.equals("Payment fail")){
            payInfoMapper.updatePayinfoStateByPayId(Long.valueOf(dto.getRefNo()), ConmonStatusEnum.FAIL.getCode());
        }
//        需要从列表中移除的情况;没有的订单号
        if(response.equals("Invalid Parameters") || response.equals("Incorrect amount") ||
                response.equals("Payment fail") || response.equals("M88Admin") || response.equals("Record not found")){
            this.delObjFromRedisList(dto); //从缓存中移除 订单
        }
    }

    /**
     * 由于返回的是状态等；无法确定其他的信息；暂时只能用异步来更改订单的状态
     * @param dto
     */
    @Override
    public void pushObjToRedisList(IpayQueryDto dto) {
        Jedis jedis = RedisClient.getJedis();
        jedis.zadd(RedisCacheEnum.REDIS_IPAY88PAY_ORDER.getCode(),1.0, JSON.toJSONString(dto));
    }
    /***
     * 定时产出N条数据去查询：此部分修改成；定时从数据库查询10条待定数据；并且待定超过半个小时；
    * */
    @Override
    public void popObjFromRedisAndQuery(int num) {
        Jedis jedis = RedisClient.getJedis();
        Set<String> setDate = jedis.zrevrange(RedisCacheEnum.REDIS_IPAY88PAY_ORDER.getCode(), 0, num);
        for(String String: setDate){
           IpayQueryDto ipayDto =  JSON.parseObject(String,IpayQueryDto.class);
           this.doQueryToIpay88(ipayDto);
        }
    }

    @Override
    public void delObjFromRedisList(IpayQueryDto dto) {
        Jedis jedis = RedisClient.getJedis();
        jedis.zrem(RedisCacheEnum.REDIS_IPAY88PAY_ORDER.getCode(),JSON.toJSONString(dto));

    }

    @Transactional
    @Override
    public void reciveIpay88CallBack(Ipay88Back dto) throws NoSuchAlgorithmException {
        //检测Ip
        log.info("==reciveIpay88CallBack==getIp===[{}]",HttpUtil.getIp());
        //检验加密
        BigDecimal amountDecimal  = new BigDecimal(dto.getAmount()).multiply(new BigDecimal(100));
        Long amountLong = amountDecimal.setScale(2, BigDecimal.ROUND_HALF_UP).longValue();
        String paramStr =   CommonConsts.MERCHANTKEY + CommonConsts.MERCHANTCODE + dto.getPaymentId() + dto.getRefNo() + amountLong + "MYR" + dto.getStatus() ;
        String mysign = SHA256.calculateSha256(paramStr);
        log.info("paramStr====={}",paramStr);
        log.info("mysign====={}",mysign);
        log.info("getSignature====={}",dto.getSignature());
        if(mysign.equals(dto.getSignature())){
            log.info("==sign==id===correct===[{}]",dto.getRefNo());
            //检测订单是否存在；
            QueryWrapper<SysPayinfo> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("pay_id",dto.getRefNo());
            SysPayinfo sysPayinfo =  payInfoMapper.selectOne(queryWrapper);
            if(sysPayinfo == null){
                return;
            }
            //检测是否被更新过
            if(sysPayinfo.getUpdateAt() != null){
                log.info("ipay88CallBack======ischangede");
                return ;
            }
            //检测金额
//            if(sysPayinfo.getMoney().compareTo(new BigDecimal(dto.getAmount())) == 1){
//                log.info("ipay88CallBack=======Money==less==");
//                return;
//            }
            UpdateWrapper<SysPayinfo> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("pay_id",dto.getRefNo());
            SysPayinfo updateObj = new SysPayinfo();
            updateObj.setUpdateAt(new Date());
            sysPayinfo.setState(Integer.valueOf(dto.getStatus()));
            sysPayinfo.setTransId(dto.getTransId());
            sysPayinfo.setPaymentId(dto.getPaymentId());
            sysPayinfo.setCcName(dto.getCCName());
            sysPayinfo.setCcNo(dto.getCCNo());
            sysPayinfo.setSBankname(dto.getS_bankname());
            sysPayinfo.setSCountry(dto.getS_country());
            int updateNum = payInfoMapper.update(sysPayinfo,updateWrapper);
            //如果是成功更新订单状态为已支付
            if(updateNum > 0 && Integer.valueOf(dto.getStatus())== ConmonStatusEnum.SUCCESS.getCode()){
                log.info("reciveIpay88CallBack====update==orderIsSuccess===={}",dto.getRefNo());
                //如果是商户费用支付更新支付；
                if(Constants.PAY_ORDER_TYPE_ORDER == sysPayinfo.getType() ){
                    log.info("reciveIpay88CallBack===is========order======");
                    OrderEditReq orderEditReq = new OrderEditReq();
                    orderEditReq.setOid(Long.valueOf( dto.getRefNo() ));
                    orderEditReq.setState(OrderStatusEnum.PAID.getCode().toString());
                    sysOrderService.changeOrderState(orderEditReq);
                }else{
                    log.info("reciveIpay88CallBack===is========dealer======");
                    //更新商户为已支付
                    sysDealerMapper.updateDealerIsPaid(Long.valueOf( dto.getRefNo() ));
                }
            }
        }else{
            log.info("ERR====SIGN==mysign={}",mysign);
        }
    }

    public static void main(String[] args) {
        Ipay88ServiceImpl obj = new Ipay88ServiceImpl();
        IpayQueryDto dto = new IpayQueryDto();
        dto.setRefNo("123456");
        dto.setAmount("0.2");
        dto.setPayType(0);
//        obj.pushObjToRedisList(dto);
//        Set setObj = obj.popObjFromRedisList(10);
        obj.doQueryToIpay88(dto);
    }
}
